#ifndef __CONNECTION_POOL__
#define __CONNECTION_POOL__

#include <st.h>
#include "ursax.h"
#include "anysocket.h"
#include "log.h"
#include "utcache.h"
#include "common.h"
#include "st-hack.h"

#ifdef __cplusplus
extern "C" {
#endif

int cconnection_pool_init(size_t capacity);

int cconnection_pool_fini();

st_netfd_t get_connection(uint32_t ip, uint16_t port);

static inline uint64_t ccpool_make_key(uint32_t ip, uint16_t port)
{
	return ((uint64_t)port << 32) | ip;
}

static inline void close_connection(uint32_t ip, uint16_t port, st_netfd_t stfd)
{
	if(st_is_socket_limit(stfd)){
		return;
	}
	if(!stfd){
		return;
	}

	LOG_DEBUG("close_old socket stfd %p (%s:%d)", stfd, str_ip(ip), port);
	st_free_rw_lock(stfd);
	st_clear_socket_error(stfd);
	st_netfd_close(stfd);
}

static inline int put_connection(uint32_t ip, uint16_t port, st_netfd_t stfd)
{
	st_put_read_lock(stfd);
	st_put_write_lock(stfd);
	extern struct foo_cache* ccpool;
	uint64_t key = ccpool_make_key(ip, port);
	return foo_cache_adjust_reference(ccpool, key, -1);
}

static inline uint32_t
get_connection_number(void)
{
	extern struct foo_cache* ccpool;
	if (NULL != ccpool) {
		return (uint32_t)foo_cache_entry_count(ccpool);
	} else {
		return 0;
	}
}
void trash_connection(uint32_t ip, uint16_t port, st_netfd_t stfd);

#define conn_record st_netfd_t
#define the_connection(x) (x)
#include "pooled-functions.h"
#undef the_connection
#undef conn_record

#ifdef __cplusplus
}
#endif

#endif
